<?php
namespace app\service;

use think\facade\Log;
use Exception;

class AiEvaluationService extends AiService
{
    /**
     * 评估用户回答并给出评分
     * 
     * 该方法用于:
     * 1. 从对话历史中提取用户最后一次回答
     * 2. 获取相关的上下文对话内容
     * 3. 根据标准答案和评分标准对用户回答进行AI评分
     * 4. 返回包含分数、是否及格和分析说明的评分结果
     * 
     * @param array $messages 对话历史消息数组
     * @param string $correctAnswer 标准答案
     * @param array $scoringCriteria 评分标准,包含total(总分)和passing(及格分)
     * @return array 评分结果,包含score(分数)、passed(是否及格)和analysis(分析说明)
     * @throws Exception 评分过程出错时抛出异常
     */
    const MAX_REFERENCE_ROUNDS = 3; // 获取最近参考对话轮数
    
    public function evaluateUserAnswer(array $messages, string $correctAnswer, array $scoringCriteria): array
    {
        // 提取用户的最后一次回答
        $userAnswer = '';
        $relevantHistory = [];
        
        // 从后向前遍历，找到最后一次用户回答和相关对话
        foreach (array_reverse($messages) as $message) {
            if ($message['role'] === 'system') {
                continue;
            }
            
            if (empty($userAnswer) && $message['role'] === 'user') {
                $userAnswer = $message['content'];
            }
            
            $relevantHistory[] = $message;
            
            // 只取最近的N轮对话
            if (count($relevantHistory) >= self::MAX_REFERENCE_ROUNDS * 2) {
                break;
            }
        }
        $relevantHistory = array_reverse($relevantHistory);
        
        // 构建评分提示
        $evaluationPrompt = "你是一位专业的答案评分助手。请根据以下信息对用户的回答进行评分：

相关对话上下文：
" . implode("\n", array_map(function($msg) {
    return ($msg['role'] === 'user' ? '用户' : 'AI') . ": " . $msg['content'];
}, $relevantHistory)) . "

标准答案：
{$correctAnswer}

评分标准：
总分：{$scoringCriteria['total']}分
及格分数：{$scoringCriteria['passing']}分

请严格按照以下JSON格式输出评分结果（不要包含任何其他文字）：
{
    \"score\": 分数,
    \"passed\": true/false,
    \"analysis\": \"评分依据和分析说明\"
}

评分要求：
1. 根据答案的完整性、准确性进行评分
2. 考虑用户理解程度和表达方式
3. 明确指出是否达到及格标准
4. 给出主要的评分依据";

        try {
            // 记录评分开始
            Log::debug('开始评分：', [
                'user_answer' => $userAnswer,
                'correct_answer' => $correctAnswer,
                'scoring_criteria' => $scoringCriteria
            ]);
            
            // 构建消息数组
            $evaluationMessages = [
                [
                    'role' => 'system',
                    'content' => $evaluationPrompt
                ]
            ];
            
            // 用于存储评分结果
            $responseText = '';
            
            // 调用AI进行评分
            $this->streamChat($evaluationMessages, function($chunk) use (&$responseText) {
                $responseText .= $chunk;
            });
            
            Log::debug('AI评分响应：', [
                'response' => $responseText
            ]);
            
            // 尝试解析JSON响应
            if (preg_match('/\{.*\}/s', $responseText, $matches)) {
                $jsonStr = $matches[0];
                $result = json_decode($jsonStr, true);
                
                if ($result && isset($result['score']) && isset($result['passed']) && isset($result['analysis'])) {
                    // 规范化结果
                    $result['score'] = floatval($result['score']);
                    $result['passed'] = boolval($result['passed']);
                    
                    Log::info('评分完成：', [
                        'score' => $result['score'],
                        'passed' => $result['passed']
                    ]);
                    
                    return $result;
                } else {
                    Log::warning('评分结果解析失败：', [
                        'json_string' => $jsonStr,
                        'json_error' => json_last_error_msg()
                    ]);
                    throw new Exception('评分结果格式不正确');
                }
            } else {
                Log::warning('未找到有效的JSON结构：', [
                    'response_text' => $responseText
                ]);
                throw new Exception('评分结果格式不正确');
            }
            
        } catch (Exception $e) {
            Log::error('评分过程出错：', [
                'error_message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }
} 